package com.lych.server.service;

import cn.hutool.core.collection.CollUtil;
import com.lych.autoconfig.template.OssTemplate;
import com.lych.commons.utils.Constants;
import com.lych.dubbo.api.CommentApi;
import com.lych.dubbo.api.MovementApi;
import com.lych.dubbo.api.UserInfoApi;
import com.lych.dubbo.api.VisitorsApi;
import com.lych.model.domain.UserInfo;
import com.lych.model.enums.CommentType;
import com.lych.model.mongo.Comment;
import com.lych.model.mongo.Movement;
import com.lych.model.mongo.Visitors;
import com.lych.model.vo.ErrorResult;
import com.lych.model.vo.MovementsVo;
import com.lych.model.vo.PageResult;
import com.lych.model.vo.VisitorsVo;
import com.lych.server.exception.BusinessException;
import com.lych.server.interceptor.UserHolder;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class MovementsService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private CommentApi commentApi;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Autowired
    private MqMessageService mqMessageService;

    /**
     * 动态-发布
     * @param movement
     * @param imageContent
     */
    public void movements(Movement movement, MultipartFile[] imageContent) throws IOException {
        //判断发布内容受否存在
        if (StringUtils.isEmpty(movement.getTextContent())){
            throw new BusinessException(ErrorResult.contentError());
        }
        //获得当前用户id
        Long userId = UserHolder.getUserId();
        //将文件上传到阿里云OSS，获取请求地址
        List<String> urls = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String url = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            urls.add(url);
        }

        //将数据封装到movements对象
        movement.setMedias(urls);
        movement.setUserId(userId);
        //调用api完成发布
        Movement movement1 = movementApi.movements(movement);
        //发送日志消息
        mqMessageService.sendLogService(userId,"0201","movement",movement1.getId().toString());

    }

    /**
     * 我的动态
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult all(Long userId, Integer page, Integer pagesize) {
        //调用api，得到分页后的动态信息
        PageResult pr = movementApi.all(userId,page,pagesize);
        //得到信息
        List<Movement> items = (List<Movement>) pr.getItems();
        //判断是否为空
        if (items == null) {
            return pr;
        }
        //得到userinfo对应的数据
        UserInfo userInfo = userInfoApi.findById(userId);
        //将信息融合，得到返回值对象
        List<MovementsVo> list = new ArrayList<>();
        for (Movement item : items) {
            MovementsVo vo = MovementsVo.init(userInfo,item);
            list.add(vo);
        }
        pr.setItems(list);
        return pr;
    }

    /**
     * 查询好友动态
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findFriendMovements(Integer page, Integer pagesize) {
        //获得当前用户id
        Long userId = UserHolder.getUserId();
        //得到详细的动态内容
        List<Movement> items = movementApi.findFriendMovements(userId,page,pagesize);
        //非空判断
        if (CollUtil.isEmpty(items)) {
            return new PageResult();
        }
        //得到好友id
        List<Long> userIds = CollUtil.getFieldValues(items, "userId", Long.class);
        //通过好友id得到详细用户信息
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);
        //封装对象并返回
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement item : items) {
            MovementsVo vo = MovementsVo.init(map.get(item.getUserId()),item);
            vos.add(vo);
        }
        return new PageResult(page,pagesize,0,vos);
    }

    /**
     * 推荐动态
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult recommend(Integer page, Integer pagesize) {
        //拼接redis中推荐动态对应的key
        String redisKey = "MOVEMENTS_RECOMMEND_" + UserHolder.getUserId();
        //通过key拿到redis中的值
        String data = redisTemplate.opsForValue().get(redisKey);
        //定义一个集合存放推荐动态
        List<Movement> list = new ArrayList<>();
        //判断缓存中是否有数据
        if (StringUtils.isEmpty(data)) {
            //没有数据，调用方法随机添加
            list = movementApi.randomMovements(pagesize);
        } else {
            String[] split = data.split(",");
            if ((page - 1) * pagesize > split.length){
                return new PageResult();
            }
            //根据分页条数拿到对应需要的pid
            List<Long> pids = new ArrayList<>();
            int path = (page - 1) * pagesize;
            for (int i = 0; i < pagesize; i++){
                pids.add(Long.parseLong(split[path + i]));
            }
            //根据pid查询对应动态信息
            list = movementApi.findByPids(pids);
        }
        //通过list中动态信息，拿到用户的id
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);
        //通过用户id拿到拿到用户详细信息
        Map<Long, UserInfo> infoMap = userInfoApi.findByIds(userIds,null);

        //封装成对象返回
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : list) {
            MovementsVo vo = MovementsVo.init(infoMap.get(movement.getUserId()), movement);
            vos.add(vo);
        }
        return new PageResult(page,pagesize,0,vos);


    }

    /**
     * 根据id查询动态
     * @param movementId
     * @return
     */
    public MovementsVo movementFindById(String movementId) {
        //根据动态id调用api进行查询
        Movement movement = movementApi.findById(movementId);
        //非空判断
        if (movement == null) {
            return null;
        }
        //根据查询到的动态查询用户具体信息
        UserInfo userInfo = userInfoApi.findById(movement.getUserId());
        //发送日志消息
        mqMessageService.sendLogService(UserHolder.getUserId(),"0202","movement",movementId);
        //封装对象，返回
        return MovementsVo.init(userInfo, movement);

    }

    /**
     * 点赞
     * @param movementId
     * @return
     */
    public Integer idLike(String movementId) {
        //调用api查看是否已经点赞
        Boolean hasComment = commentApi.hasComment(movementId,UserHolder.getUserId(),CommentType.LIKE);
        //如果点赞了，抛出异常
        if (hasComment) {
            throw new BusinessException(ErrorResult.likeError());
        }
        //调用api保存数据
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());
        comment.setCommentType(CommentType.LIKE.getType());
        comment.setPublishId(new ObjectId(movementId));
        comment.setUserId(UserHolder.getUserId());
        Integer integer = commentApi.saveComments(comment);
        //拼接key，将用户点赞信息存入redis
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        //发送日志消息
        mqMessageService.sendLogService(UserHolder.getUserId(),"0203","movement",movementId);
        return integer;
    }

    /**
     * 取消点赞
     * @param movementId
     * @return
     */
    public Integer idDisLike(String movementId) {
        //调用api查看用户是否点赞
        Boolean hasComment = commentApi.hasComment(movementId, UserHolder.getUserId(), CommentType.LIKE);
        //如果没有点赞，抛出异常
        if (!hasComment) {
            throw new BusinessException(ErrorResult.disLikeError());
        }
        //调用api删除数据
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setUserId(UserHolder.getUserId());
        comment.setCommentType(CommentType.LIKE.getType());
        Integer count = commentApi.delete(comment);
        //拼接key，删除点赞状态
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        //发送日志消息
        mqMessageService.sendLogService(UserHolder.getUserId(),"0206","movement",movementId);
        return count;
    }


    /**
     * 喜欢
     * @param movementId
     * @return
     */
    public Integer idLove(String movementId) {
        //调用api查看是否已经喜欢
        Boolean flag = commentApi.hasComment(movementId, UserHolder.getUserId(), CommentType.LOVE);
        //如果已经喜欢，抛异常
        if (flag) {
            throw  new BusinessException(ErrorResult.loveError());
        }
        //调用api保存数据
        Comment comment = new Comment();
        comment.setCommentType(CommentType.LOVE.getType());
        comment.setCreated(System.currentTimeMillis());
        comment.setUserId(UserHolder.getUserId());
        comment.setPublishId(new ObjectId(movementId));
        Integer integer = commentApi.saveComments(comment);
        //拼接redis中的key，将点赞状态存入
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        //发送消息日志
        mqMessageService.sendLogService(UserHolder.getUserId(),"0204","movement",movementId);
        return integer;
    }

    /**
     * 动态取消喜欢
     * @param movementId
     * @return
     */
    public Integer idUnlove(String movementId) {
        //调用api查看是否已经喜欢
        Boolean aBoolean = commentApi.hasComment(movementId, UserHolder.getUserId(), CommentType.LOVE);
        //如果没有喜欢，抛异常
        if (!aBoolean) {
            throw new BusinessException(ErrorResult.disloveError());
        }
        //调用api，删除数据，返回喜欢数
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setUserId(UserHolder.getUserId());
        comment.setCommentType(CommentType.LOVE.getType());
        Integer integer = commentApi.delete(comment);
        //拼接key，删除redis中的喜欢数据
        String key = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        //发送消息日志
        mqMessageService.sendLogService(UserHolder.getUserId(),"0206","movement",movementId);
        return integer;
    }

    /**
     * 谁看过我
     * @return
     */
    public List<VisitorsVo> visitors() {
        String key = Constants.VISITORS;
        String hashKey = String.valueOf(UserHolder.getUserId());
        String value = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long date = StringUtils.isEmpty(value) ? null:Long.valueOf(value);
        //调用api，查询谁看过我
        List<Visitors> list = visitorsApi.visitors(date,UserHolder.getUserId());
        //非空判断
        if (CollUtil.isEmpty(list)){
            return new ArrayList<>();
        }
        //得到访客的id
        List<Long> ids = CollUtil.getFieldValues(list, "visitorUserId", Long.class);
        //查询访客具体信息
        Map<Long, UserInfo> infoMap = userInfoApi.findByIds(ids, null);
        //构造对象返回
        List<VisitorsVo> vos = new ArrayList<>();
        for (Visitors visitors : list) {
            UserInfo userInfo = infoMap.get(visitors.getVisitorUserId());
            if (userInfo != null) {
                VisitorsVo vo = VisitorsVo.init(userInfo,visitors);
                vos.add(vo);
            }
        }
        return vos;
    }
}
